// This is an instruction checker for Y86 SEQ implement
// 1. It generates clock and reset signals to make the Y86 run
// 2. Check Y86 stat signal.
// 3. It just records all GPR, CC, PC to a log file on the posedge of clock

`include "define.v"
`include "hier_seq.v"

module Check (
    /*AUTOARG*/);

    // clock
    initial begin
        top.clock = 1'b0;
        forever begin
            #10 top.clock = ~top.clock;
        end
    end

    initial begin
        #200000
        $display("ERROR: system may hang!");
        $finish;
    end

    // reset
    initial begin
        top.reset = 1'b1;
        repeat(5)
        @(negedge top.clock);
        top.reset = 1'b0;
    end
    
    // record
    integer REC_FILE;
    initial begin
        REC_FILE = $fopen("record.log", "w");
    end

    integer i = 0;
    integer step = 0;
    always @(posedge top.clock, posedge top.reset)begin
        #1; // add some hold time and then print log
        if(top.reset)begin
        end else begin
            step = step + 1;
            $fdisplay(REC_FILE, "%0d steps, PC = 0x%0h, Status = %h, CC = %b%b%b", 
                step, `PC, `STAT, `CC[2], `CC[1], `CC[0]);
            $fdisplay(REC_FILE, "eax = 0x%8h", `EAX);
            $fdisplay(REC_FILE, "ecx = 0x%8h", `ECX);
            $fdisplay(REC_FILE, "edx = 0x%8h", `EDX);
            $fdisplay(REC_FILE, "ebx = 0x%8h", `EBX);
            $fdisplay(REC_FILE, "esp = 0x%8h", `ESP);
            $fdisplay(REC_FILE, "ebp = 0x%8h", `EBP);
            $fdisplay(REC_FILE, "esi = 0x%8h", `ESI);
            $fdisplay(REC_FILE, "edi = 0x%8h", `EDI);
        end
        if (`STAT != `SAOK)begin
            //$fdisplay(REC_FILE, "CPU status is %h, stop simulation\n", `STAT);
            $fdisplay(REC_FILE, "Final Memory Image:");
            for(i=0; i<=`BMEMSIZE/8; i=i+1)begin
                $display("i=%d", i);
                $display("0x%4h: 0x%8h", i<<3  , {`BMEM3, `BMEM2, `BMEM1, `BMEM0});
                $display("0x%4h: 0x%8h", (i<<3)+4, {`BMEM7, `BMEM6, `BMEM5, `BMEM4});
                if({`BMEM3, `BMEM2, `BMEM1, `BMEM0} != 32'h0000_0000)begin
                    $fdisplay(REC_FILE, "0x%4h: 0x%8h", i<<3  , {`BMEM3, `BMEM2, `BMEM1, `BMEM0});
                end
                if({`BMEM7, `BMEM6, `BMEM5, `BMEM4} != 32'h0000_0000)begin
                    $fdisplay(REC_FILE, "0x%4h: 0x%8h", (i<<3)+4, {`BMEM7, `BMEM6, `BMEM5, `BMEM4});
                end
            end
            $fdisplay(REC_FILE, "runtime = %0d", $time);
            $fclose(REC_FILE);
            repeat(5)
            @(posedge top.clock);
            $finish;
        end
    end

endmodule

